package com.blank.client;

import com.blank.model.Quiz;
import com.blank.model.TestReport;
import com.blank.model.User;
import com.blank.model.UserMessage;
import com.blank.util.ClientScanner;
import com.blank.util.CommonUtil;
import com.blank.util.ConstEnum;

import java.io.*;
import java.util.LinkedList;

/**
 * 实现客户端的主界面绘制和相应功能的实现
 */
public class ClientView {

    /**
     * 本地存储考题信息 txt 文件路径
     */
    private static final String MY_QUIZZES_LOCAL_FILE_PATH = "./ExamClient/src/MyQuizzes.txt";

    /**
     * 本地存储考试成绩报告 txt 文件路径
     */
    private static final String MY_TEST_REPORT_LOCAL_FILE_PATH = "./ExamClient/src/MyTestReport.txt";

    /**
     * 采用合成复用原则。私有化 ClientInitClose 类型的对象，从而得到其中的输入输出流
     */
    private ClientInitClose cic;

    /**
     * 通过构造方法实现成员变量的初始化
     */
    public ClientView(ClientInitClose cic) {
        this.cic = cic;
    }

    /**
     * 实现客户端主界面的绘制
     */
    public void clientMainPage() throws IOException, ClassNotFoundException {
        while (true) {
            System.out.println("\n\n\t\t\t\t在线考试系统");
            System.out.println("-------------------------------------------");
            System.out.print("   [1] 学员系统");
            System.out.println("     [2] 管理员系统");
            System.out.println("   [0] 退出系统");
            System.out.println("-------------------------------------------");
            System.out.println("请选择要进行的业务编号：");

            int choose = ClientScanner.getScanner().nextInt();
            switch (choose) {
                case 1:
                    studentSystemPage();
                    break;
                case 2:
                    managerSystemPage();
                    break;
                case 0:
                    clientExit();
                    return;
                default:
                    System.out.println("输入错误，请重新选择");
            }
        }
    }

    /**
     * 管理员系统的页面绘制
     */
    private void managerSystemPage() throws IOException, ClassNotFoundException {
        // 如果登录失败，则直接返回
        if (!clientManagerLogin()) {
            return;
        }

        // 无限循环绘制管理员系统的主界面和实现相应的功能
        while (true) {
            System.out.println("\n\n\t\t\t\t管理员系统");
            System.out.println("-------------------------------------------");
            System.out.print("   [1] 学员管理");
            System.out.println("     [2] 考题管理");
            System.out.println("   [0] 退出");
            System.out.println("-------------------------------------------");
            System.out.println("请选择要进行的业务编号：");

            int choose = ClientScanner.getScanner().nextInt();
            switch (choose) {
                case 1:
                    manageStudentInfoPage();
                    break;
                case 2:
                    manageExamInfoPage();
                    break;
                case 0:
                    clientLogout();
                    return;
                default:
                    System.out.println("输入错误，请重新选择");
            }
        }
    }

    /**
     * 学员管理模块的页面绘制
     */
    private void manageStudentInfoPage() throws IOException, ClassNotFoundException {
        // 无限循环绘制学员管理模块主页面和实现相应的功能
        while (true) {
            System.out.println("\n\n\t\t\t\t学生管理");
            System.out.println("-------------------------------------------");
            System.out.print("   [1] 增加学生");
            System.out.println("     [2] 删除学生");
            System.out.print("   [3] 修改学生");
            System.out.println("     [4] 查找学生");
            System.out.print("   [5] 遍历学生");
            System.out.println("     [0] 返回");
            System.out.println("-------------------------------------------");
            System.out.println("请选择要进行的业务编号：");

            int choose = ClientScanner.getScanner().nextInt();
            switch (choose) {
                case 1:
                    addStudent();
                    break;
                case 2:
                    deleteStudent();
                    break;
                case 3:
                    updateStudent();
                    break;
                case 4:
                    searchStudent();
                    break;
                case 5:
                    printAllStudents();
                    break;
                case 0:
                    return;
                default:
                    System.out.println("输入错误，请重新选择");
            }
        }
    }


    /**
     * 考题管理模块的页面绘制
     */
    private void manageExamInfoPage() throws IOException, ClassNotFoundException {
        // while死循环绘制考题管理模块主页面和实现相应的功能
        while (true) {
            System.out.println("\n\n\t\t\t\t考题管理");
            System.out.println("-------------------------------------------");
            System.out.print("   [1] 增加考题");
            System.out.println("     [2] 删除考题");
            System.out.print("   [3] 修改考题");
            System.out.println("     [4] 查询考题");
            System.out.print("   [5] 导入考题");
            System.out.println("     [0] 返回");
            System.out.println("-------------------------------------------");
            System.out.println("请选择要进行的业务编号：");

            int choose = ClientScanner.getScanner().nextInt();
            switch (choose) {
                case 1:
                    addQuiz();
                    break;
                case 2:
                    deleteQuiz();
                    break;
                case 3:
                    updateQuiz();
                    break;
                case 4:
                    searchQuiz();
                    break;
                case 5:
                    loadQuizzesFromFile();
                    break;
                case 0:
                    return;
                default:
                    System.out.println("输入错误，请重新选择");
            }
        }
    }

    /**
     * 学员系统的页面绘制
     */
    private void studentSystemPage() throws IOException, ClassNotFoundException {
        // 如果登录失败，则直接返回
        if (!clientStudentLogin()) {
            return;
        }

        // while死循环绘制学员系统的主界面和实现相应的功能
        while (true) {
            System.out.println("\n\n\t\t\t\t学员系统");
            System.out.println("-------------------------------------------");
            System.out.print("   [1] 开始考试");
            System.out.println("     [2] 查询成绩");
            System.out.print("   [3] 导出成绩");
            System.out.println("     [4] 修改密码");
            System.out.println("   [0] 退出");
            System.out.println("-------------------------------------------");
            System.out.println("请选择要进行的业务编号：");

            int choose = ClientScanner.getScanner().nextInt();
            switch (choose) {
                case 1:
                    startTest();
                    break;
                case 2:
                    queryTestReport();
                    break;
                case 3:
                    saveTestReport();
                    break;
                case 4:
                    updatePassword();
                    break;
                case 0:
                    clientLogout();
                    return;
                default:
                    System.out.println("输入错误，请重新选择");
            }
        }
    }

    /**
     * 实现客户端的管理员登录

     */
    private boolean clientManagerLogin() throws IOException, ClassNotFoundException {
        // 从控制台获取管理员登录相关的数据
        System.out.println("请输入管理员账户的用户名：");
        String username =  ClientScanner.getScanner().next().strip();
        System.out.println("请输入管理员账户的密码：");
        String password = ClientScanner.getScanner().next().strip();
        UserMessage userMessage = new UserMessage(ConstEnum.MANAGER_CHECK, new User(username, password));

        // 将 UserMessage 类型的对象通过对象输出流发送给服务器
        cic.getOos().writeObject(userMessage);
        System.out.println("发送管理员账户信息到服务器...");

        // 接受服务器的处理结果并给出提示
        userMessage = CommonUtil.cast(cic.getOis().readObject());
        if (ConstEnum.SUCCESS == userMessage.getType()) {
            System.out.println("登录成功，欢迎光临");
            return true;
        } else {
            System.out.println("用户名或者密码错误");
            return false;
        }
    }

    /**
     * 实现客户端的学员登录
     */
    private boolean clientStudentLogin() throws IOException, ClassNotFoundException {
        // 从控制台获取学员登录相关的数据
        System.out.println("请输入学员账户的用户名：");
        String username =  ClientScanner.getScanner().next().strip();
        System.out.println("请输入学员账户的密码：");
        String password = ClientScanner.getScanner().next().strip();
        UserMessage userMessage = new UserMessage(ConstEnum.USER_CHECK, new User(username, password));

        // 将 UserMessage 类型的对象通过对象输出流发送给服务器
        cic.getOos().writeObject(userMessage);
        System.out.println("发送学员账户信息到服务器...");

        // 接受服务器的处理结果并给出提示
        userMessage = CommonUtil.cast(cic.getOis().readObject());
        if (ConstEnum.SUCCESS == userMessage.getType()) {
            System.out.println("登录成功，欢迎光临");
            return true;
        } else {
            System.out.println("用户名或者密码错误");
            return false;
        }
    }

    /**
     * 发送账户登出信息到服务器
     */
    private void clientLogout() throws IOException {
        UserMessage userMessage = new UserMessage(ConstEnum.LOGOUT, null);
        cic.getOos().writeObject(userMessage);
        System.out.println("发送账户登出信息到服务器");
    }

    /**
     * 发送退出信息到服务器
     */
    private void clientExit() throws IOException {
        UserMessage userMessage = new UserMessage(ConstEnum.EXIT, null);
        cic.getOos().writeObject(userMessage);
        System.out.println("发送退出信息到服务器");
    }

    /**
     * 实现学员增加功能
     */
    private void addStudent() throws IOException, ClassNotFoundException {
        // 从控制台获取新学员相关的数据
        System.out.println("请输入新增学员的用户名：");
        String username =  ClientScanner.getScanner().next().strip();
        System.out.println("请输入新增学员的密码：");
        String password = ClientScanner.getScanner().next().strip();
        UserMessage userMessage = new UserMessage(ConstEnum.ADD_STUDENT, new User(username, password));

        // 将 UserMessage 类型的对象通过对象输出流发送给服务器
        cic.getOos().writeObject(userMessage);
        System.out.println("发送新增学员的信息到服务器...");

        // 接受服务器的处理结果并给出提示
        userMessage = CommonUtil.cast(cic.getOis().readObject());
        if (ConstEnum.SUCCESS == userMessage.getType()) {
            System.out.println("学员新增成功");
        } else {
            System.out.println("学员信息重复，新增失败");
        }
    }

    /**
     * 实现学员的删除功能
     */
    private void deleteStudent() throws IOException, ClassNotFoundException {
        // 从控制台获取相关的数据
        System.out.println("请输入要删除的学员的用户名：");
        String username =  ClientScanner.getScanner().next().strip();
        UserMessage userMessage = new UserMessage(ConstEnum.DEL_STUDENT, new User(username, ""));

        // 将 UserMessage 类型的对象通过对象输出流发送给服务器
        cic.getOos().writeObject(userMessage);
        System.out.println("发送要删除的学员的信息到服务器...");

        // 接受服务器的处理结果并给出提示
        userMessage = CommonUtil.cast(cic.getOis().readObject());
        if (ConstEnum.SUCCESS == userMessage.getType()) {
            System.out.println("学员删除成功");
        } else {
            System.out.println("学员不存在");
        }
    }

    /**
     * 实现学员的更新功能
     */
    private void updateStudent() throws IOException, ClassNotFoundException {
        // 从控制台获取相关的数据
        System.out.println("请输入要更新的学员的用户名：");
        String username =  ClientScanner.getScanner().next().strip();
        System.out.println("请输入要更新的学员的密码：");
        String password = ClientScanner.getScanner().next().strip();
        UserMessage userMessage = new UserMessage(ConstEnum.UPD_STUDENT, new User(username, password));

        // 将 UserMessage 类型的对象通过对象输出流发送给服务器
        cic.getOos().writeObject(userMessage);
        System.out.println("发送要更新的学员的信息到服务器...");

        // 接受服务器的处理结果并给出提示
        userMessage = CommonUtil.cast(cic.getOis().readObject());
        if (ConstEnum.SUCCESS == userMessage.getType()) {
            System.out.println("学员更新成功");
        } else {
            System.out.println("学员不存在");
        }
    }

    /**
     * 实现学员的查找功能
     */
    private void searchStudent() throws IOException, ClassNotFoundException {
        // 从控制台获取相关的数据
        System.out.println("请输入要查找的学员的用户名：");
        String username =  ClientScanner.getScanner().next().strip();
        UserMessage userMessage = new UserMessage(ConstEnum.GET_STUDENT, new User(username, ""));

        // 将 UserMessage 类型的对象通过对象输出流发送给服务器
        cic.getOos().writeObject(userMessage);
        System.out.println("发送要查找的学员的信息到服务器...");

        // 接受服务器的处理结果并给出提示
        userMessage = CommonUtil.cast(cic.getOis().readObject());
        if (ConstEnum.SUCCESS == userMessage.getType()) {
            System.out.println("查找成功：" + userMessage.getUser());
        } else {
            System.out.println("学员不存在");
        }
    }

    /**
     * 实现遍历所有学员的功能
     */
    private void printAllStudents() throws IOException, ClassNotFoundException {
        // 将 UserMessage 类型的对象通过对象输出流发送给服务器
        cic.getOos().writeObject(new UserMessage(ConstEnum.PRINT_ALL_STUDENTS, null));
        System.out.println("发送遍历所有学生信息请求到服务器...");

        // 接受服务器返回的所有学生信息并输出到控制台
        LinkedList<User> userList = CommonUtil.cast(cic.getOis().readObject());
        System.out.println("获取的所有学生信息如下：");
        if (null == userList || userList.isEmpty()) {
            System.out.println("{空}");
        } else {
            userList.forEach(System.out::println);
        }
    }

    /**
     * 实现增加考题的功能
     */
    private void addQuiz() throws IOException, ClassNotFoundException {
        // 从控制台获取考题相关的数据
        System.out.println("请输入新考题的内容：");
        String content = ClientScanner.getScanner().next().strip();
        System.out.print("选项A：");
        String a = ClientScanner.getScanner().next().strip();
        System.out.print("选择B：");
        String b = ClientScanner.getScanner().next().strip();
        System.out.print("选项C：");
        String c = ClientScanner.getScanner().next().strip();
        System.out.print("选择D：");
        String d = ClientScanner.getScanner().next().strip();
        System.out.print("答案：");
        String answer = ClientScanner.getScanner().next().strip();
        Quiz quiz = new Quiz(content+"\nA:"+a+"\nB:"+b+"\nC:"+c+"\nD:"+d, answer);

        // 发送增加考题的请求给服务器
        UserMessage userMessage = new UserMessage(ConstEnum.ADD_QUIZ, null);
        cic.getOos().writeObject(userMessage);

        // 发送考题本身到服务器
        cic.getOos().writeObject(quiz);

        // 接受服务器的处理结果并给出提示
        userMessage = CommonUtil.cast(cic.getOis().readObject());
        if (ConstEnum.SUCCESS == userMessage.getType()) {
            System.out.println("增加考题成功");
        } else {
            System.out.println("增加考题失败");
        }
    }

    /**
     * 实现删除考题的功能
     */
    private void deleteQuiz() throws IOException, ClassNotFoundException {
        // 从控制台获取考题相关的数据
        System.out.println("请输入要被删除的考题部分内容：");
        String keyString = ClientScanner.getScanner().next().strip();

        // 发送删除考题的请求给服务器
        UserMessage userMessage = new UserMessage(ConstEnum.DEL_QUIZ, null);
        cic.getOos().writeObject(userMessage);

        // 发送要删除的考题相关的内容到服务器
        cic.getOos().writeObject(keyString);

        // 接受服务器的处理结果并给出提示
        userMessage = CommonUtil.cast(cic.getOis().readObject());
        if (ConstEnum.SUCCESS == userMessage.getType()) {
            System.out.println("删除考题成功");
        } else {
            System.out.println("考题不存在");
        }
    }

    /**
     * 实现更新考题的功能
     */
    private void updateQuiz() throws IOException, ClassNotFoundException {
        // 从控制台获取考题相关的数据
        System.out.println("请输入要修改的考题的内容：");
        String keyString = ClientScanner.getScanner().next().strip();
        System.out.println("请输入修改后的考题的选项和答案：");
        System.out.print("选项A：");
        String a = ClientScanner.getScanner().next().strip();
        System.out.print("选择B：");
        String b = ClientScanner.getScanner().next().strip();
        System.out.print("选项C：");
        String c = ClientScanner.getScanner().next().strip();
        System.out.print("选择D：");
        String d = ClientScanner.getScanner().next().strip();
        System.out.print("答案：");
        String answer = ClientScanner.getScanner().next().strip();

        // 先发送修改考题的请求给服务器
        UserMessage userMessage = new UserMessage(ConstEnum.UPD_QUIZ, null);
        cic.getOos().writeObject(userMessage);

        // 发送要更新的考题相关的内容以及修改后考题的选项和答案到服务器
        cic.getOos().writeObject(keyString);
        cic.getOos().writeObject("\nA:"+a+"\nB:"+b+"\nC:"+c+"\nD:"+d);
        cic.getOos().writeObject(answer);

        // 接受服务器的处理结果并给出提示
        userMessage = CommonUtil.cast(cic.getOis().readObject());
        if (ConstEnum.SUCCESS == userMessage.getType()) {
            System.out.println("修改考题成功");
        } else {
            System.out.println("考题不存在");
        }
    }

    /**
     * 实现查找考题的功能
     */
    private void searchQuiz() throws IOException, ClassNotFoundException {
        // 从控制台获取考题相关的数据
        System.out.println("请输入要查找的考题部分内容：");
        String keyString = ClientScanner.getScanner().next().strip();

        // 发送查找考题的请求给服务器
        cic.getOos().writeObject(new UserMessage(ConstEnum.GET_QUIZ, null));

        // 发送要查找的考题相关的内容到服务器
        cic.getOos().writeObject(keyString);

        // 接受服务器返回的考题并打印结果
        Quiz quiz = CommonUtil.cast(cic.getOis().readObject());
        if (null != quiz) {
            System.out.println("查找成功，考题信息如下：");
            System.out.println(quiz);
        } else {
            System.out.println("考题不存在");
        }
    }

    /**
     * 实现导入考题功能
     */
    private void loadQuizzesFromFile() throws ClassNotFoundException {
        File file = new File(MY_QUIZZES_LOCAL_FILE_PATH);
        if (!file.exists()) {
            System.out.println("文件不存在，无法导入考题，请按照格式要求添加文件：" + MY_QUIZZES_LOCAL_FILE_PATH);
            return;
        }
        // 用输入流从本地文件读取考题并通过输出流发送到服务器
        BufferedReader br = null;
        try {
            // 初始化文件输入流，考题集合以及相关字符串变量
            br = new BufferedReader(new FileReader(file));
            LinkedList<Quiz> quizzes = new LinkedList<>();

            // 循环读取并加入到考题集合中
            int num = Integer.parseInt(br.readLine().strip());
            String content, a, b, c, d, answer;
            for (int i = 0; i < num; i++) {
                content = br.readLine().strip();
                a = br.readLine().strip();
                b = br.readLine().strip();
                c = br.readLine().strip();
                d = br.readLine().strip();
                answer = br.readLine().strip();
                quizzes.add(new Quiz(content+"\nA:"+a+"\nB:"+b+"\nC:"+c+"\nD:"+d, answer));
            }

            // System.out.println("导入的考题如下：");
            // quizzes.forEach(System.out::println);

            // 发送导入考题的请求给服务器
            cic.getOos().writeObject(new UserMessage(ConstEnum.LOAD_QUIZZES, null));

            // 考题集合作为对象流输出到服务器
            cic.getOos().writeObject(quizzes);

            // 接受服务器的处理结果并给出提示
            UserMessage userMessage = CommonUtil.cast(cic.getOis().readObject());
            if (ConstEnum.SUCCESS == userMessage.getType()) {
                System.out.println("导入考题成功，文件来源：" + MY_QUIZZES_LOCAL_FILE_PATH);
            } else {
                System.out.println("导入考题失败");
            }

        } catch (IOException e) {
            // e.printStackTrace();
            System.out.println("MyQuizzes 文件读取异常：" + e.getMessage());
        } finally {
            // 释放输入流资源
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 实现学员考试功能
     */
    private void startTest() throws IOException, ClassNotFoundException {
        // 发送考试请求到服务器
        cic.getOos().writeObject(new UserMessage(ConstEnum.START_TEST, null));

        // 接受服务器发送的三道考题内容
        String[] quizContent = CommonUtil.cast(cic.getOis().readObject());
        if (quizContent == null) {
            System.out.println("题库没有数据或数据不足，考试无法开始。");
            return;
        }

        // 开始考试，读取学员的答案
        System.out.println("\n\t\t\t\t考试开始");
        System.out.println("-------------------------------------------");
        String[] studentAnswer = new String[3];
        for (int i = 0; i < 3; i++) {
            System.out.println("第" + (i + 1) + "题");
            System.out.println(quizContent[i]);
            System.out.print("你的选择：");
            studentAnswer[i] = ClientScanner.getScanner().next().strip();
            System.out.println();
        }

        // 发送学员的答案到服务器
        cic.getOos().writeObject(studentAnswer);

        // 提示考试结束
        System.out.println("-------------------------------------------");
        System.out.println("\t\t\t\t谢谢参与，考试结束\n");
    }

    /**
     * 实现查询考试成绩功能
     */
    private void queryTestReport() throws IOException, ClassNotFoundException {
        // 发送考试成绩查询请求到服务器
        cic.getOos().writeObject(new UserMessage(ConstEnum.GET_TEST_REPORT, null));

        // 接受服务器发送的考试成绩报告
        TestReport testReport = CommonUtil.cast(cic.getOis().readObject());
        if (testReport == null) {
            System.out.println("没有考试成绩");
            return;
        }

        // 打印考试成绩到控制台
        System.out.println(testReport);
    }

    /**
     * 下载考试成绩报告到本地
     */
    private void saveTestReport() throws IOException, ClassNotFoundException {
        // 发送考试成绩查询请求到服务器
        cic.getOos().writeObject(new UserMessage(ConstEnum.GET_TEST_REPORT, null));

        // 接受服务器发送的考试成绩报告
        TestReport testReport = CommonUtil.cast(cic.getOis().readObject());
        if (testReport == null) {
            System.out.println("没有考试成绩");
            return;
        }

        // 以 txt 文件格式保存考试报告到客户端本地
        File file = new File(MY_TEST_REPORT_LOCAL_FILE_PATH);
        BufferedWriter bw = null;
        try {
            // 如果存储文件不存在则创建文件
            if (!file.exists()) {
                System.out.println(file.createNewFile() ? "考试成绩报告文件创建成功" : "考试成绩报告文件创建失败");
            } else {
                System.out.println("考试成绩报告文件已存在，将被新报告文件覆盖...");
            }
            // 建立输出流
            bw = new BufferedWriter(new FileWriter(file));
            // 保存考试成绩报告信息
            bw.write(testReport.toString());
            bw.flush();
            System.out.println("成功导出成绩到文件：" + MY_TEST_REPORT_LOCAL_FILE_PATH);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != bw) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 实现学员修改密码功能
     */
    private void updatePassword() throws IOException, ClassNotFoundException {
        // 从控制台获取新密码
        System.out.println("请输入新密码：");
        String password = ClientScanner.getScanner().next().strip();
        UserMessage userMessage = new UserMessage(ConstEnum.UPDATE_PASSWORD, new User("", password));

        // 将 UserMessage 类型的对象通过对象输出流发送给服务器
        cic.getOos().writeObject(userMessage);
        System.out.println("发送新密码到服务器...");

        // 接受服务器的处理结果并给出提示
        userMessage = CommonUtil.cast(cic.getOis().readObject());
        if (ConstEnum.SUCCESS == userMessage.getType()) {
            System.out.println("密码修改成功");
        } else {
            System.out.println("密码修改失败");
        }

    }
}
